Color Animation, Part II
Volume Number: 10
Issue Number: 5
Column Tag: Getting Started
Related Info: Color Manager
Color Animation, Part II
GWorlds, Bitmaps, PixMaps, and CopyBits - getting the bits flying
By Dave Mark, MacTech Magazine Regular Contributing Author
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Last month’s column introduced PixMapper, a colorized version of last
September’s BitMapper program. BitMapper caused a black and white BitMap to float
over a patterned background with absolutely no flicker (Figure 1). BitMapper based
its magic on a series of three offscreen BitMaps, BitMaps created in memory but not
visible on the screen. The first offscreen contains the foreground image (the
left-pointing hand). The second offscreen contains the background image (the grey,
framed rectangle). The third offscreen is used to combine the foreground and
background before drawing the combined image into the BitMapper window.
Figure 1. Last September’s BitMapper program.
Why does this work? Rather than erasing the old image and repainting it in a new
position in the window (in BitMapper’s case, the hand tracks the position of the mouse,
sort of a giant cursor), this algorithm repeatedly repaints the entire window, based on
the contents of the combining offscreen BitMap. Just as a movie consisting of a series
of still frames appears to be a single animated image, the constant repainting of the
BitMapper window gives the appearance of an animated image.
Adding Color to the Algorithm
As you’d expect, PixMapper achieves the same affect in color by using PixMaps
instead of BitMaps. Just as a BitMap describes a black and white bit pattern, a PixMap
describes a color bit pattern. Unfortunately, animation with PixMaps is not quite as
simple as its black and white counterpart. Why? A PixMap is just more complex.
While a BitMap’s pixels are all either black or white, a PixMap’s pixels can be any
one of a number of colors, depending on the depth of the PixMap.
The BitMap data structure is relatively simple:
struct BitMap
{
Ptr baseAddr;
short rowBytes;
Rect bounds;
};
Now compare the BitMap to the PixMap data structure:
struct PixMap
{
Ptr baseAddr; /*pointer to pixels*/
short rowBytes; /*offset to next line*/
Rect bounds; /*encloses bitmap*/
short pmVersion; /*pixMap version number*/
short packType; /*defines packing format*/
long packSize; /*length of pixel data*/
Fixed hRes; /*horiz. resolution (ppi)*/
Fixed vRes; /*vert. resolution (ppi)*/
short pixelType; /*defines pixel type*/
short pixelSize; /*# bits in pixel*/
short cmpCount; /*# components in pixel*/
short cmpSize; /*# bits per component*/
long planeBytes; /*offset to next plane*/
CTabHandle pmTable; /*color map for this pixMap*/
long pmReserved; /*for future use. MUST BE 0*/
};
As you can see, the PixMap data structure is far more complicated. In addition,
while BitMapper used a GrafPort, PixMapper must use a CGrafPort. As you might
suspect, setting up a CGrafPort is more complicated than setting up its black and white
counterpart.
The GWorld
Fortunately, rather than forcing you to go through the arduous process of
creating and maintaining these far more complex structures, the Toolbox offers a
terrific shortcut, namely, the GWorld.
The GWorld is a full-color, offscreen drawing environment. Just as you’d use an
offscreen GrafPort and BitMap to prepare a black and white image for blitting to the
screen (blitting comes from an old term BLT, which stood for BLock Transfer, meaning
to copy a block of memory from one area to another, all at once), you’ll use a GWorld
to do the same for a color image. PixMapper demonstrates all this and a little bit more.
Before we get into the code, let’s take a quick look back at PixMapper in action.
Running PixMapper
The PixMapper menu bar features four menus: Apple, File, Edit, and Colors.
PixMapper features a single window filling the entire main screen (see
GetMainDevice()). PixMapper fills this window with randomly colored squares. Once
the window is completely drawn, PixMapper loads a PICT resource, and uses a series of
offscreen GWorlds to animate the PICT across the colored background. The speed of
your PICT will depend on the speed of your machine and the size of the PICT. The
important thing to notice is that the PICT animates smoothly with absolutely no
flicker. If there is any hesitation, it is most likely due to the system taking time to do
some housekeeping chore. Notice that PixMapper works, even if the PICT is
non-rectangular or has a hole in it (see Figure 2).
Figure 2. PixMapper in action.
The PICT starts in the upper-left corner of the window and moves towards the
lower right corner. Every time the PICT hits the edge of the window, the PICT will
bounce off and continue in the opposite direction.
When you select Redraw from the File menu, PixMapper redraws the window and
starts the animation over again.
Go to the Colors menu and play with all the different menu settings. PixMapper
lets you play with both the RGB and HSV color models. RGB lets you set a color’s red,
green, and blue values. If you uncheck Random Reds, for example, the screen will be
redrawn with a red value of 0 (all greens and blues). If Random Reds is checked, the
red component of the color is a random value from 0 to 65535.
If you select HSV Colors, you’ll be able to work with hue, saturation, and
brightness rather than red, green, and blue. Unlike the RGB menu items, if you
uncheck Random Hues, a color’s hues component is set to 65535 instead of 0. Play
around with these settings. Do you think you’ll get different results when you choose
random RGB versus when you choose random hues?
To learn more about color and the RGB and HSV color models, read “About the
Color Manager” in Inside Macintosh, Volume V, THINK Reference or in the upcoming
volume Inside Macintosh: Imaging.
The PixMapper Source Code
PixMapper starts off with three critical #includes. has all the
GWorld defines, has the definitions needed to work with the RGB and HSV
data structures and routines, and has the definitions you’ll need to work
with Gestalt(). Take a few minutes to look through these three include files.
/* 1 */
#include
#include
#include
There are a lot of #defines used in this program. As usual, they’ll all be
described as they occur in the code.
/* 2 */
#define kMBARResID 128
#define kSleep 0L
#define kMoveToFront (WindowPtr)-1L
#define kEmptyString "\p
#define kEmptyTitle kEmptyString
#define kVisible true
#define kNoGoAway false
#define kNilRefCon (long)nil
#define kErrorAlertID 128
#define kNilFilterProc nil
#define kSquareSize 16
#define kForegroundPICT 128
#define kIgnored nil
#define kUseMaxDepth 0
#define kNoFlags (GWorldFlags)0
#define mApple 128
#define iAbout 1
#define mFile 129
#define iRedraw 1
#define iQuit 3
#define mColors 131
#define iUseRGB 1
#define iUseHSV 2
#define iRed 4
#define iGreen 5
#define iBlue 6
#define iHue 4
#define iSaturation 5
#define iBrightness 6
PixMapper uses a bunch of globals. gDone starts life as false and is set to true
when Quit is selected from the File menu. gIsRGB is true when the RGB Colors item is
selected from the Colors menu, false when HSV Colors is selected. gRandomReds,
gRandomGreens, and gRandomBlues are true when their respective items are selected
from the Colors menu. The same holds true for gRandomHue, gRandomSaturation, and
gRandomBrightness.
/* 3 */
Boolean gDone;
Boolean gIsRGB = true, gRandomReds = true,
gRandomGreens = true, gRandomBlues = true;
Boolean gRandomHue = true, gRandomSaturation = true,
gRandomBrightness = true;
gMainWindow points to the window with all the colors and the animated PICT.
gXBump and gYBump specify the number of pixels the PICT moves each new animation
cycle. One way to speed up the animation is to raise the bump values, though the code